#pragma once
#ifndef LIST__H__
#define LIST__H__

#ifndef _AUTOMOBILE_H
#include "..\engine\memorymanager.h"
#endif
template<typename T>
class List
{
private:
	struct Item
	{
	public:
		T		m_pData; 
		Item	*m_pNext; 
		Item	*m_pPrev; 

		Item(T pData)
		{
			m_pData = pData; 
			m_pNext = NULL; 
			m_pPrev = NULL; 
		}

		virtual ~Item(void)		{ m_pNext = NULL;  m_pPrev = NULL;  }
	}; 

	unsigned int	m_Length; 
	Item			*m_pRoot; 
	Item			*m_pHead; 
	Item			*m_pItterator; 

	void Remove(Item *ptr); 

public:
	List(void); 
	void Add(T ptr); 
	T	beginItteration(void); 
	T nextItteration(void); 
	void	endItteration(void); 
	void Empty(void); 
	void Remove(T ptr); 
	void Remove(unsigned int index); 
	unsigned int Length(void); 
}; 

template<class T>
void List<T>::Remove(unsigned int index)
{
	Item	*ptr = m_pHead; 
	
	while(index > 0 && ptr)
	{
		ptr = ptr->m_pNext; 
		index--; 
	}

	if(ptr)
		Remove(ptr); 
}

template<class T>
void List<T>::Remove(Item *ptr)
{
	Item	*pNext = ptr->m_pNext; 
	Item	*pPrev = ptr->m_pPrev; 

	if(pNext && pPrev)
	{
		pPrev->m_pNext = pNext; 
		pNext->m_pPrev = pPrev; 
	}
	else if(pNext && !pPrev)
	{
		m_pRoot = pNext; 
		pNext->m_pPrev = NULL; 
	}
	else if(pPrev && !pNext)
	{
		m_pHead = pPrev; 
		pPrev->m_pNext = NULL; 
	}

	if(ptr == m_pRoot) m_pRoot = NULL; 
	if(ptr == m_pHead) m_pHead = NULL; 

	EE_SAFEDELETE(ptr); 
	ptr = NULL; 
}

template<class T>
List<T>::List(void)	
{ 
	m_Length = 0;  
	m_pHead = NULL;  
	m_pRoot = NULL;  
	m_pItterator = NULL;  
}

template<class T>
void List<T>::Add(T ptr)
{
	m_pItterator = NULL; 

	Item	*pItem = EE_NEW Item(ptr); 

	if(m_pRoot == NULL)
	{
		m_pRoot = pItem; 
		m_pHead = pItem; 
	}
	else
	{
		pItem->m_pPrev = m_pHead; 
		m_pHead->m_pNext = pItem; 
		m_pHead = pItem; 
	}

	m_Length++; 
}

template<class T>
T List<T>::beginItteration(void)	
{ 
	m_pItterator = m_pRoot;  
	return m_pRoot->m_pData;  
}

template<class T>
T List<T>::nextItteration(void)
{
	T	itterator; 

	m_pItterator = m_pItterator->m_pNext; 

	if(m_pItterator)
		itterator = m_pItterator->m_pData; 
	else
		memset(&itterator, 0, sizeof(T)); 

	return itterator; 
}

template<class T>
void List<T>::endItteration(void)		
{ 
	m_pItterator = NULL;  
}

template<class T>
void List<T>::Empty(void)
{
	m_pItterator = NULL; 

	Item	*pItem = m_pRoot; 
	while(pItem)
	{
		Item	*pCurrent = pItem; 
		pItem = pItem->m_pNext; 

		EE_SAFEDELETE(pCurrent); 
	}

	m_pRoot = NULL; 
	m_pHead = NULL; 
	m_Length = 0; 
}

template<class T>
void List<T>::Remove(T ptr)
{
	m_pItterator = NULL; 

	Item	*pSearch = m_pRoot; 
	while(pSearch)
	{
		Item	*pCheck = pSearch; 
		pSearch = pSearch->m_pNext; 

		if(pCheck->m_pData == ptr)
		{
			m_Length--; 
			EE_SAFEDELETE(pCheck); 
		}
	}
}

template<class T>
unsigned int List<T>::Length(void)	
{ 
	return m_Length;  
}

#endif LIST__H__
